package com.sprite.utils;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Collections;
import java.util.Enumeration;
import java.util.LinkedList;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


/**
 * @author Jack
 */
public class UtilURL {

    private static final Logger logger = LoggerFactory.getLogger(UtilURL.class);

    public static <C> URL fromClass(Class<C> contextClass) {
        String resourceName = contextClass.getName();
        int dotIndex = resourceName.lastIndexOf('.');

        if (dotIndex != -1) resourceName = resourceName.substring(0, dotIndex);
        resourceName += ".properties";

        return fromResource(contextClass, resourceName);
    }

    public static URL fromResource(String resourceName) {
        return fromResource(resourceName, null);
    }

    /**
     * 从指定类的加载器中加载资源
     *
     * @param contextClass
     *         上下文
     * @param resourceName
     *         资源名称
     * @param <C>
     *         泛型类型
     * @return 资源地址
     */
    public static <C> URL fromResource(Class<C> contextClass, String resourceName) {
        if (contextClass == null)
            return fromResource(resourceName, null);
        else
            return fromResource(resourceName, contextClass.getClassLoader());
    }

    /**
     * 根据资源名加载资源
     *
     * @param resourceName
     *         资源名称
     * @param loader
     *         如果为空，默认当前线程的加载器
     * @return 资源地址
     */
    public static URL fromResource(String resourceName, ClassLoader loader) {
        if (loader == null) {
            try {
                loader = Thread.currentThread().getContextClassLoader();
            } catch (SecurityException e) {
                UtilURL utilURL = new UtilURL();
                loader = utilURL.getClass().getClassLoader();
            }
        }

        // 1、从classloader 加载资源
        URL url = loader.getResource(resourceName);
        if (url != null) {
            return url;
        }
        String propertiesResourceName = null;

        // 2、追加properties后缀
        if (!resourceName.endsWith(".properties")) {
            propertiesResourceName = resourceName.concat(".properties");
            url = loader.getResource(propertiesResourceName);
            if (url != null) {
                return url;
            }
        }

        // 3、加载系统资源
        url = ClassLoader.getSystemResource(resourceName);
        if (url != null) {
            return url;
        }
        if (propertiesResourceName != null) {
            url = ClassLoader.getSystemResource(propertiesResourceName);
            if (url != null) {
                return url;
            }
        }

        // 4、从文件系统中加载
        url = fromFilename(resourceName);
        if (url != null) {
            return url;
        }

        // 5、从url中加载
        url = fromUrlString(resourceName);
        return url;
    }

    /**
     * 加载多个资源
     *
     * @param resourceName
     *         资源名称
     * @return 资源集合
     * @throws IOException
     *         io读写错误
     */
    public static List<URL> fromResources(String resourceName) throws IOException {
        return fromResources(resourceName, null);
    }

    /**
     * 加载多个资源
     *
     * @param resourceName
     *         资源名称
     * @param loader
     *         ClassLoader
     * @return 资源集合
     * @throws IOException
     *         ClassLoader
     * @see #fromResource(String, ClassLoader)
     */
    public static List<URL> fromResources(String resourceName, ClassLoader loader) throws IOException {
        if (loader == null) {
            try {
                loader = Thread.currentThread().getContextClassLoader();
            } catch (SecurityException e) {
                UtilURL utilURL = new UtilURL();
                loader = utilURL.getClass().getClassLoader();
            }
        }
        Enumeration<URL> enumeration = loader.getResources(resourceName);
        if (enumeration != null && enumeration.hasMoreElements()) {
            List<URL> list = new LinkedList<URL>();
            while (enumeration.hasMoreElements()) {
                URL url2 = enumeration.nextElement();
                list.add(url2);
            }

            if (!list.isEmpty()) {
                return list;
            }
        }

        String propertiesResourceName = null;
        if (!resourceName.endsWith(".properties")) {
            propertiesResourceName = resourceName.concat(".properties");
            enumeration = loader.getResources(propertiesResourceName);
            if (enumeration != null && enumeration.hasMoreElements()) {
                List<URL> list = new LinkedList<URL>();
                while (enumeration.hasMoreElements()) {
                    URL url2 = enumeration.nextElement();
                    list.add(url2);
                }
                return list;
            }
        }
        enumeration = ClassLoader.getSystemResources(resourceName);

        if (enumeration != null && enumeration.hasMoreElements()) {
            List<URL> list = new LinkedList<URL>();
            while (enumeration.hasMoreElements()) {
                URL url2 = enumeration.nextElement();
                list.add(url2);
            }
            return list;
        }

        if (propertiesResourceName != null) {
            enumeration = ClassLoader.getSystemResources(propertiesResourceName);
            if (enumeration != null && enumeration.hasMoreElements()) {
                List<URL> list = new LinkedList<URL>();
                while (enumeration.hasMoreElements()) {
                    URL url2 = enumeration.nextElement();
                    list.add(url2);
                }
                return list;
            }
        }
        URL url = fromFilename(resourceName);
        if (url != null) {
            return UtilMisc.toList(url);
        }
        url = fromUrlString(resourceName);
        if (url != null) {
            return UtilMisc.toList(url);
        }

        return Collections.emptyList();
    }


    public static URL fromFilename(String filename) {
        if (filename == null) return null;
        File file = new File(filename);
        URL url = null;

        try {
            if (file.exists()) url = file.toURI().toURL();
        } catch (java.net.MalformedURLException e) {
            logger.error("", e);
            url = null;
        }
        return url;
    }

    public static URL fromUrlString(String urlString) {
        URL url = null;
        try {
            url = new URL(urlString);
        } catch (MalformedURLException e) {
        }

        return url;
    }


    /**
     * 读取文本
     *
     * @param url
     *         URL
     * @return 文本
     * @throws IOException
     *         io错误
     */
    public static String readUrlText(URL url) throws IOException {
        InputStream stream = url.openStream();

        StringBuilder buf = new StringBuilder();
        BufferedReader in = null;
        try {
            in = new BufferedReader(new InputStreamReader(stream));

            String str;
            while ((str = in.readLine()) != null) {
                buf.append(str);
                buf.append(System.getProperty("line.separator"));
            }
        } catch (IOException e) {
            throw e;
        } finally {
            if (in != null) {
                try {
                    in.close();
                } catch (IOException e) {
                    logger.error("", e);
                }
            }
        }

        return buf.toString();
    }
}
